﻿using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Newtonsoft.Json;
using WebSocket4Net;

namespace WebSocketClientTestTool
{
    public partial class FormMain : Form
    {
        private static WebSocket _ws;
        private static bool _isOpen;

        public FormMain()
        {
            InitializeComponent();

            var config = GetConfig();
            txtBoxWSAddress.Text = config.WebSocketAddress;

            if (config.PresetSendData != null && config.PresetSendData.Length > 0)
            {
                comboBoxSendData.Items.AddRange(config.PresetSendData);
                comboBoxSendData.AutoCompleteSource = AutoCompleteSource.ListItems;
                comboBoxSendData.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            }
        }
        
        private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            _ws?.Close();
            _ws?.Dispose();
        }

        private AppConfig GetConfig()
        {
            var configFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json");

            var sr = new StreamReader(configFilePath);
            var json = sr.ReadToEnd();
            sr.Close();

            return JsonConvert.DeserializeObject<AppConfig>(json);
        }

        private void btnOpenWS_Click(object sender, EventArgs e)
        {
            if (!_isOpen)
            {
                var address = txtBoxWSAddress.Text.Trim();

                if (address.Length == 0)
                {
                    MessageBox.Show(@"地址不能为空");
                    return;
                }

                _ws = new WebSocket(address);
                _ws.Open();

                _ws.Opened += (o, args) =>
                {
                    Invoke(new Action(() =>
                    {
                        btnOpenWS.Text = @"断开连接";
                        richTextBoxDataRecv.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "\t【已连接】\n");
                        _isOpen = true;
                    }));
                };

                _ws.Closed += (o, args) => 
                {
                    Invoke(new Action(() =>
                    {
                        btnOpenWS.Text = @"打开连接";
                        richTextBoxDataRecv.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "\t【已断开】\n");
                        _isOpen = false;
                    }));
                };

                _ws.MessageReceived += (o, args) =>
                {
                    Invoke(new Action(() =>
                    {
                        var recvMsg = args.Message;
                        var data = checkBoxFormatJson.Checked ? FormatJsonString(recvMsg) : recvMsg;
                        AppendRichText("【接收】", data, Color.FromArgb(60, 130, 180));
                    }));
                };
            }
            else
            {
                _ws?.Close();
                _isOpen = false;
            }
        }
        
        private void btnSend_Click(object sender, EventArgs e)
        {
            if (_ws == null || _ws.State != WebSocketState.Open)
            {
                MessageBox.Show(@"请先打开连接");
                return;
            }

            var sendData = comboBoxSendData.Text.Trim();

            if (sendData.Length == 0)
            {
                MessageBox.Show(@"发送的数据不能为空");
                return;
            }

            _ws.Send(sendData);
            
            AppendRichText("【发送】", sendData, Color.FromArgb(224, 122, 0));
        }
        
        private void comboBoxSendData_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue == 13)
            {
                btnSend_Click(btnSend, null);
            }
        }

        private void btnClearRecvData_Click(object sender, EventArgs e)
        {
            richTextBoxDataRecv.Clear();
        }
        
        private string FormatJsonString(string json)
        {
            try
            {
                var serializer = new JsonSerializer();
                var tr = new StringReader(json);
                var jtr = new JsonTextReader(tr);
                var obj = serializer.Deserialize(jtr);

                if (obj == null) return json;

                var textWriter = new StringWriter();
                var jsonWriter = new JsonTextWriter(textWriter)
                {
                    Formatting = Formatting.Indented,
                    Indentation = 4,
                    IndentChar = ' '
                };
                serializer.Serialize(jsonWriter, obj);
                return textWriter.ToString();
            }
            catch (Exception)
            {
                return json;
            }
        }

        private void AppendRichText(string title, string text, Color color)
        {
            richTextBoxDataRecv.AppendText($"{DateTime.Now:yyyy-MM-dd HH:mm:ss:fff}\t{title}\n");

            var startLine = richTextBoxDataRecv.GetFirstCharIndexOfCurrentLine() - 1;
            var selectionStartIndex = richTextBoxDataRecv.TextLength;

            richTextBoxDataRecv.AppendText(text + "\n");
            richTextBoxDataRecv.Select(selectionStartIndex, text.Length);
            richTextBoxDataRecv.SelectionColor = color;
            richTextBoxDataRecv.SelectionStart = startLine;
            richTextBoxDataRecv.ScrollToCaret();
        }

        private void btnHelp_Click(object sender, EventArgs e)
        {
            new FormHelp().ShowDialog();
        }
    }

    public class AppConfig
    {
        public string WebSocketAddress { get; set; }
        /// <summary>
        /// 预置数据
        /// </summary>
        public string[] PresetSendData { get; set; }
    }
}
